package com.ruicar.afs.cloud.basic.common.controller;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.basic.api.dto.ManageOverpaymentDifferenceDto;
import com.ruicar.afs.cloud.basic.common.condition.ReceiptRecordCondition;
import com.ruicar.afs.cloud.basic.common.entity.BasicMainInfo;
import com.ruicar.afs.cloud.basic.common.entity.BasicReceiptRecord;
import com.ruicar.afs.cloud.basic.common.service.BasicMainInfoService;
import com.ruicar.afs.cloud.basic.common.service.BasicReceiptRecordService;
import com.ruicar.afs.cloud.basic.common.vo.ReceiptRecordVo;
import com.ruicar.afs.cloud.basic.proceeds.debit.entity.BasicDebitBatchDetails;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitBatchDetailsService;
import com.ruicar.afs.cloud.batch.entity.AfsBatchInfo;
import com.ruicar.afs.cloud.batch.service.AfsBatchInfoService;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.contract.enums.DebitStatusEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.ReceiptSourceTypeEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.ReceiptStatusEnum;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.common.vo.CollectCancelVo;
import com.ruicar.afs.cloud.common.vo.ReceiptDetailVo;
import com.ruicar.afs.cloud.manage.api.dto.BankArriveInfoDto;
import com.ruicar.afs.cloud.manage.api.feign.cust.CustChangeFeign;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.*;

/**
 * <p>Description: </p>
 *
 * @author ZC.GUO
 * @version 1.0
 * @date create on 2020-07-31 14:40
 */

@Slf4j
@RestController
@RequestMapping("/receiptHandle")
@AllArgsConstructor
public class BasicReceiptRecordController {

    private final BasicReceiptRecordService basicReceiptRecordService;
    private final BasicMainInfoService basicMainInfoService;
    private final BasicDebitBatchDetailsService basicDebitBatchDetailsService;
    private CustChangeFeign custChangeFeign;
    private final AfsBatchInfoService afsBatchInfoService;

    public Date getBatchDate() {
        return DateUtil.parse(afsBatchInfoService.getSystemBatchInfo("icos").getBatchDate(), DatePattern.PURE_DATE_PATTERN);
    }


    /**
     * 收款撤销拒绝收据处理
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/receiptHandleForCancelReject")
    @ApiOperation(value = "收款撤销拒绝收据处理")
    @Transactional(rollbackFor = Exception.class)
    public IResponse receiptHandleForCancelReject(@RequestParam("receiptId") Long receiptId, @RequestParam("operator") String operator) {
        BasicReceiptRecord receiptRecord = basicReceiptRecordService.getById(receiptId);
        if (EmptyUtils.isNotEmpty(receiptRecord)) {
            receiptRecord.setReceiptStatus(ReceiptStatusEnum.creditSuccess);
            receiptRecord.setUndoEndTime(Calendar.getInstance().getTime());
            receiptRecord.setCaseNo("");
            basicReceiptRecordService.updateById(receiptRecord);
            return IResponse.success("处理成功");
        } else {
            return IResponse.fail("合同系统中无此收据id");
        }
    }

    /**
     * 收款撤销发起收据处理
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/receiptHandleForCancelStart")
    @ApiOperation(value = "收款撤销发起收据处理")
    @Transactional(rollbackFor = Exception.class)
    public IResponse receiptHandleForCancelStart(@RequestParam("receiptId") Long receiptId, @RequestParam("caseNo") String caseNo) {
        BasicReceiptRecord receiptRecord = basicReceiptRecordService.getById(receiptId);
        //判断流程发起时，是否时按照时间顺序倒叙撤销，或流程已在流程中不可撤销
        List<BasicReceiptRecord> list = basicReceiptRecordService.list(Wrappers.<BasicReceiptRecord>query().lambda().eq(BasicReceiptRecord::getContractNo, receiptRecord.getContractNo())
                .ne(BasicReceiptRecord::getId, receiptId).
                        and(wrapper1 -> wrapper1.gt(BasicReceiptRecord::getCreateTime, receiptRecord.getCreateTime()).eq(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.creditSuccess)
                                .or(wrapper2 -> wrapper2.eq(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.revokeExamine))
                        ));
        if (EmptyUtils.isNotEmpty(list)) {
            BasicReceiptRecord record = list.get(0);
            log.error(MessageFormat.format("本次撤销不可发起:{0}", record.getReceiptStatus().equals(ReceiptStatusEnum.creditSuccess) ? "需要按照时间顺序倒叙撤销" : "已有撤销合同在流程中"));
            return IResponse.fail(MessageFormat.format("本次撤销不可发起:{0}", record.getReceiptStatus().equals(ReceiptStatusEnum.creditSuccess) ? "需要按照时间顺序倒叙撤销" : "已有撤销合同在流程中"));
        }
        BasicMainInfo basicMainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getContractNo, receiptRecord.getContractNo())
        );
        if (EmptyUtils.isEmpty(basicMainInfo)) {
            return IResponse.fail("合同号不存在");
        } else if (basicMainInfo.getCloseDate() != null) {
            return IResponse.fail("合同已关闭");
        }
        if (EmptyUtils.isNotEmpty(receiptRecord)) {
            receiptRecord.setReceiptStatus(ReceiptStatusEnum.revokeExamine);
            receiptRecord.setCaseNo(caseNo);
            receiptRecord.setUndoStartTime(Calendar.getInstance().getTime());
            basicReceiptRecordService.updateById(receiptRecord);
            return IResponse.success("处理成功");
        } else {
            return IResponse.fail("合同系统中无此收据id");
        }
    }

    /**
     * 收款撤销通过收据处理
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/receiptHandleForCancel")
    @ApiOperation(value = "收款撤销通过收据处理")
    public IResponse receiptHandleForCancelAgree(@RequestParam("receiptId") String receiptId, @RequestParam("operator") String operator) {
        AfsBatchInfo afsBatchInfo = afsBatchInfoService.getSystemBatchInfo("icos"); // 判断是否在宽限期内
        Long id = null;
        try {
            id = Long.parseLong(receiptId);
        } catch (NumberFormatException e) {
            return IResponse.fail("处理失败");
        }
        return basicReceiptRecordService.handleReceiptForCancel(id, operator, afsBatchInfo, getBatchDate());
    }

    @ApiOperation(value = "根据合同号码、案件编号获取收据分配明细信息")
    @PostMapping("/getReceiptRecordInfo")
    public IResponse getReceiptRecordInfo(@RequestBody ReceiptRecordCondition condition) {
        return IResponse.success(basicReceiptRecordService.getReceiptRecordInfo(condition.getContractNo(), condition.getReceiptId()));
    }

    @ApiOperation(value = "根据合同号码获取收据信息")
    @PostMapping("/getReceiptRecordList")
    public IResponse getReceiptRecordList(@RequestBody ReceiptRecordCondition condition) {
        BasicMainInfo mainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda().eq(BasicMainInfo::getContractNo, condition.getContractNo()));
        if (EmptyUtils.isEmpty(mainInfo)) {
            return IResponse.fail("合同号不存在");
        }
        List<CollectCancelVo> collectCancelVos = basicReceiptRecordService.getReceiptRecord(condition);
        ReceiptDetailVo vo = new ReceiptDetailVo();
        vo.setCollectCancelVos(collectCancelVos);
        return IResponse.success(vo);
    }

    @ApiOperation(value = "根据id获取收据信息")
    @PostMapping("/getReceiptRecord")
    public IResponse getReceiptRecord(@RequestParam("id") Long id) {
        return IResponse.success(basicReceiptRecordService.getById(id));
    }

    @ApiOperation(value = "根据id获取收据信息")
    @PostMapping("/getCollectCancelVo")
    public IResponse getCollectCancelVo(@RequestParam("id") Long id) {
        return IResponse.success(basicReceiptRecordService.getCollectCancelVo(id));
    }

    /**
     * 获取扣款流水
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/getWithHold")
    @ApiOperation(value = "获取扣款流水")
    public IResponse<List<ReceiptRecordVo>> getWithHold(@RequestParam("contractId") String contractId) {
        Long id = 0L;
        try {
            id = Long.parseLong(contractId);
        } catch (Exception e) {
            return IResponse.fail("合同id参数错误");
        }

        List<ReceiptRecordVo> receiptRecordVoList = new ArrayList<>();
        BasicMainInfo mainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getId, id)
        );
        if (EmptyUtils.isNotEmpty(mainInfo)) {
            /**  代扣 by ZC.GUO  **/
            List<DebitStatusEnum> debitStatusEnums = new ArrayList<>();
            debitStatusEnums.add(DebitStatusEnum.successDebit);
            debitStatusEnums.add(DebitStatusEnum.failDebit);
            List<BasicDebitBatchDetails> debitBatchDetailsList = basicDebitBatchDetailsService.list(Wrappers.<BasicDebitBatchDetails>query().lambda()
                    .eq(BasicDebitBatchDetails::getContractNo, mainInfo.getContractNo())
                    .in(BasicDebitBatchDetails::getStatus, debitStatusEnums)

            );
            if (EmptyUtils.isNotEmpty(debitBatchDetailsList)) {
                debitBatchDetailsList.forEach(debitBatchDetails -> {
                    ReceiptRecordVo receiptRecordVo = new ReceiptRecordVo();
                    receiptRecordVo.setOrderDate(debitBatchDetails.getUpdateTime());
                    receiptRecordVo.setReceiptDate(DateUtil.format(debitBatchDetails.getUpdateTime(), "yyyy/MM/dd HH:mm:ss"));
                    receiptRecordVo.setReceiptAmt(debitBatchDetails.getAmount());
                    receiptRecordVo.setDrawerName(debitBatchDetails.getDebitAccountName());
                    receiptRecordVo.setBankCode(debitBatchDetails.getDebitSignBank());
                    receiptRecordVo.setAccount(debitBatchDetails.getDebitAccount());
                    receiptRecordVo.setDebitRemarks("代扣");
                    receiptRecordVo.setResRemarks(debitBatchDetails.getRemarks());
                    receiptRecordVo.setReceiptResult(DebitStatusEnum.successDebit.equals(debitBatchDetails.getStatus()) ? "成功" : "失败");
                    receiptRecordVoList.add(receiptRecordVo);
                });
            }
            /**  对公结算 by ZC.GUO  **/
            List<BasicReceiptRecord> receiptRecordList = basicReceiptRecordService.list(Wrappers.<BasicReceiptRecord>query().lambda()
                    .eq(BasicReceiptRecord::getContractNo, mainInfo.getContractNo())
                    .eq(BasicReceiptRecord::getSourceType, ReceiptSourceTypeEnum.transferAccounts)
                    .eq(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.creditSuccess)
            );
            if (EmptyUtils.isNotEmpty(receiptRecordList)) {
                receiptRecordList.forEach(receiptRecord -> {
                    ReceiptRecordVo receiptRecordVo = new ReceiptRecordVo();
                    receiptRecordVo.setOrderDate(receiptRecord.getSucceedTime());
                    receiptRecordVo.setReceiptDate(DateUtil.format(receiptRecord.getSucceedTime(), "yyyy/MM/dd HH:mm:ss"));
                    receiptRecordVo.setReceiptAmt(receiptRecord.getArriveAmt());
                    receiptRecordVo.setDrawerName(receiptRecord.getSourceAccountName());
                    receiptRecordVo.setBankCode("");
                    receiptRecordVo.setAccount(receiptRecord.getSourceAccount());
                    receiptRecordVo.setDebitRemarks("");
                    receiptRecordVo.setResRemarks("");
                    receiptRecordVo.setReceiptResult("成功");
                    IResponse<BankArriveInfoDto> iResponse = custChangeFeign.getBankArriveInfo(receiptRecord.getSourceId());
                    if (CommonConstants.SUCCESS.equals(iResponse.getCode())) {
                        BankArriveInfoDto bankArriveInfoDto = iResponse.getData();
                        receiptRecordVo.setOrderDate(bankArriveInfoDto.getArrivalTime());
                        receiptRecordVo.setReceiptDate(DateUtil.format(bankArriveInfoDto.getArrivalTime(), "yyyy/MM/dd HH:mm:ss"));
                        receiptRecordVo.setBankCode(bankArriveInfoDto.getReceivingBank());
                        receiptRecordVo.setDrawerName(bankArriveInfoDto.getPaymentCust());
                        receiptRecordVo.setDebitRemarks(bankArriveInfoDto.getSummary());
                        receiptRecordVo.setResRemarks(bankArriveInfoDto.getDealRemarks());
                    }
                    receiptRecordVoList.add(receiptRecordVo);
                });
            }
            /**  TODO ZC.GUO  微信还款对接完成后进行修改 **/
            /**  微信还款 by ZC.GUO  **/
            /**  整体按时间倒序排序 by ZC.GUO  **/
            if (receiptRecordVoList.size() > 0) {
                receiptRecordVoList.sort(Comparator.comparing(ReceiptRecordVo::getOrderDate).reversed());
            }
            return IResponse.success(receiptRecordVoList);
        } else {
            return IResponse.fail("合同id不存在");
        }
    }

    @ApiOperation(value = "根据合同号查询溢缴款信息")
    @PostMapping("/getReceiptList")
    public IResponse getReceiptRecord(@RequestParam("contractNo") String contractNo) {
        List<BasicReceiptRecord> list = basicReceiptRecordService.list(Wrappers.<BasicReceiptRecord>lambdaUpdate()
                .eq(BasicReceiptRecord::getContractNo, contractNo)
                .ne(BasicReceiptRecord::getReceiptStatus, ReceiptStatusEnum.revoke));
        return new IResponse().setData(list);
    }

    @ApiOperation(value = "更新收据表信息")
    @PostMapping("/updateReceiptRecord")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<String> updateReceiptRecord(@RequestBody ManageOverpaymentDifferenceDto overpaymentDifferenceDto) {
        List<BasicReceiptRecord> list = basicReceiptRecordService.list(Wrappers.<BasicReceiptRecord>lambdaQuery()
                .eq(BasicReceiptRecord::getContractNo, overpaymentDifferenceDto.getContractNo()));
        BigDecimal b = BigDecimal.valueOf(0);
        BigDecimal amt = new BigDecimal(0);
        for (BasicReceiptRecord basicReceiptRecord : list) {
            amt = amt.add(basicReceiptRecord.getUnusedAmt());
        }
        if (amt.compareTo(overpaymentDifferenceDto.getAmount()) != 0) {
            return new IResponse().setData("未分配金额与溢缴款数据有误，无法继续！");
        }
        for (BasicReceiptRecord basicReceiptRecord : list) {
            basicReceiptRecord.setOverpaymentAmount(basicReceiptRecord.getUnusedAmt());
            basicReceiptRecord.setUnusedAmt(b);
            basicReceiptRecordService.updateById(basicReceiptRecord);
        }

        return new IResponse().setData(Boolean.TRUE.toString());
    }
}
